/**
 * @file apdu_assembler.h
 * @brief APDU组装器 - 专门负责APDU的组装
 * @details 本文件定义了104协议的APDU组装器功能，包括I格式、S格式、U格式APDU的
 *          组装、APDU构建辅助函数等核心功能。支持完整的APDU数据组装流程，确保
 *          生成的APDU数据符合104协议规范。
 * 
 * @author zyb
 * @date 2025-10-06
 * @version 1.0
 * 
 * @note I格式APDU包含ASDU数据，S格式和U格式APDU不包含ASDU数据
 * @warning APDU组装时需要确保序列号在有效范围内，避免序列号溢出
 * 
 * @see apdu_assembler.c
 * @see protocol_types.h
 * @see constants.h
 * @see error_codes.h
 */

#ifndef APDU_ASSEMBLER_H
#define APDU_ASSEMBLER_H

#include "protocol_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== I格式APDU组装函数 ==================== */

/**
 * @brief 组装I格式APDU
 * @details 将I格式APDU结构体组装成字节流格式。I格式APDU用于传输信息数据，
 *          包含启动字符、长度、控制域（发送/接收序列号）和ASDU数据。
 *          函数会验证APDU格式和缓冲区大小，然后将APDU数据写入缓冲区。
 * 
 * @param apdu I格式APDU结构指针，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为APDU_MIN_LENGTH
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_APDU_FORMAT_ERROR: APDU格式错误
 * 
 * @note I格式APDU包含ASDU数据，长度可变
 * @warning 缓冲区必须足够大以容纳完整的APDU数据
 * 
 * @see apdu_t
 * @see is_i_format_apdu
 * @see validate_apdu
 */
protocol_error_t assemble_i_format_apdu(const apdu_t* apdu, uint8_t* buffer, size_t buffer_size, size_t* actual_size);

/**
 * @brief 组装带ASDU的I格式APDU
 * @details 直接使用ASDU数据组装I格式APDU。这是一个便捷函数，
 *          用于将ASDU数据直接封装成I格式APDU，无需先构建APDU结构。
 *          函数会验证ASDU有效性，设置序列号，然后组装成字节流。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param send_seq 发送序列号
 * @param receive_seq 接收序列号
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效ASDU类型
 * 
 * @note 此函数是assemble_i_format_apdu()的便捷版本
 * @warning 序列号必须在有效范围内（0-32767）
 * 
 * @see asdu_t
 * @see assemble_i_format_apdu
 * @see validate_asdu
 */
protocol_error_t assemble_i_format_apdu_with_asdu(const asdu_t* asdu, 
                                                  uint16_t send_seq, 
                                                  uint16_t receive_seq,
                                                  uint8_t* buffer, 
                                                  size_t buffer_size, 
                                                  size_t* actual_size);

/* ==================== S格式APDU组装函数 ==================== */

/**
 * @brief 组装S格式APDU
 * @details 组装S格式APDU，用于确认接收到的I格式APDU。S格式APDU
 *          只包含接收序列号，不包含ASDU数据，长度固定为4字节。
 *          用于实现104协议的确认机制。
 * 
 * @param receive_seq 接收序列号，表示已确认接收的I格式APDU序列号
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为4字节
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note S格式APDU长度固定为4字节，不包含ASDU数据
 * @warning 接收序列号必须在有效范围内（0-32767）
 * 
 * @see U_FORMAT_STARTDT_ACT
 * @see U_FORMAT_STARTDT_CON
 * @see U_FORMAT_STOPDT_ACT
 * @see U_FORMAT_STOPDT_CON
 * @see U_FORMAT_TESTFR_ACT
 * @see U_FORMAT_TESTFR_CON
 */
protocol_error_t assemble_s_format_apdu(uint16_t receive_seq, uint8_t* buffer, size_t buffer_size, size_t* actual_size);

/* ==================== U格式APDU组装函数 ==================== */

/**
 * @brief 组装U格式APDU
 * @details 组装U格式APDU，用于控制功能。U格式APDU不包含序列号，
 *          长度固定为4字节，用于启动/停止数据传输、测试帧等控制功能。
 *          支持STARTDT、STOPDT、TESTFR等控制类型。
 * 
 * @param u_type U格式类型，如STARTDT_ACT、STOPDT_CON等
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为4字节
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效U格式类型
 * 
 * @note U格式APDU长度固定为4字节，不包含序列号和ASDU数据
 * @warning U格式类型必须是有效的控制类型
 * 
 * @see u_format_type_t
 * @see U_FORMAT_STARTDT_ACT
 * @see U_FORMAT_STARTDT_CON
 * @see U_FORMAT_STOPDT_ACT
 * @see U_FORMAT_STOPDT_CON
 * @see U_FORMAT_TESTFR_ACT
 * @see U_FORMAT_TESTFR_CON
 */
protocol_error_t assemble_u_format_apdu(u_format_type_t u_type, uint8_t* buffer, size_t buffer_size, size_t* actual_size);

/* ==================== 通用APDU组装函数 ==================== */

/**
 * @brief 通用APDU组装函数
 * @details 根据APDU格式自动选择相应的组装函数。这是一个通用接口，
 *          会根据APDU的格式（I格式、S格式、U格式）调用相应的专用组装函数。
 *          支持所有类型的APDU组装。
 * 
 * @param apdu APDU结构指针，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_APDU_FORMAT_ERROR: APDU格式错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 此函数会根据APDU格式自动选择相应的组装函数
 * @warning 确保APDU格式正确，否则会返回格式错误
 * 
 * @see assemble_i_format_apdu
 * @see assemble_s_format_apdu
 * @see assemble_u_format_apdu
 * @see is_i_format_apdu
 * @see is_s_format_apdu
 * @see is_u_format_apdu
 */
protocol_error_t assemble_apdu(const apdu_t* apdu, uint8_t* buffer, size_t buffer_size, size_t* actual_size);

/* ==================== APDU构建辅助函数 ==================== */

/**
 * @brief 构建I格式APDU
 * @details 构建I格式APDU结构，包含发送序列号、接收序列号和ASDU数据。
 *          这是一个便捷函数，用于创建完整的I格式APDU结构。
 * 
 * @param send_seq 发送序列号，范围0-32767
 * @param receive_seq 接收序列号，范围0-32767
 * @param asdu ASDU结构指针，不能为NULL
 * @param apdu APDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 构建成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 *         - PROTOCOL_ERROR_ASDU_INVALID: ASDU无效
 * 
 * @note 构建后的APDU需要调用assemble_apdu()组装成字节流
 * @warning 序列号必须在有效范围内
 * 
 * @see assemble_apdu
 * @see validate_asdu
 * @see init_apdu
 */
protocol_error_t build_i_format_apdu(uint16_t send_seq, uint16_t receive_seq, const asdu_t* asdu, apdu_t* apdu);

/**
 * @brief 构建S格式APDU
 * @details 构建S格式APDU结构，用于确认帧传输。
 *          包含接收序列号，用于确认已接收的I格式APDU。
 *          这是一个便捷函数，用于创建完整的S格式APDU结构。
 * 
 * @param receive_seq 接收序列号，范围0-32767
 * @param apdu APDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 构建成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 * 
 * @note 构建后的APDU需要调用assemble_apdu()组装成字节流
 * @warning 序列号必须在有效范围内（0-32767）
 * 
 * @see assemble_apdu
 * @see init_apdu
 * @see S_FORMAT_CONTROL_MASK
 */
protocol_error_t build_s_format_apdu(uint16_t receive_seq, apdu_t* apdu);

/**
 * @brief 构建U格式APDU
 * @details 构建U格式APDU结构，用于控制帧传输。
 *          支持启动数据传输、停止数据传输、测试帧等控制类型。
 *          这是一个便捷函数，用于创建完整的U格式APDU结构。
 * 
 * @param u_type U格式类型，不能为NULL
 * @param apdu APDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 构建成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 * 
 * @note 构建后的APDU需要调用assemble_apdu()组装成字节流
 * @warning U格式类型必须是有效的控制类型
 * 
 * @see assemble_apdu
 * @see init_apdu
 * @see u_format_type_t
 */
protocol_error_t build_u_format_apdu(u_format_type_t u_type, apdu_t* apdu);

#ifdef __cplusplus
}
#endif

#endif /* APDU_ASSEMBLER_H */
